1 module hip.gui.screen; 2 public import hip.gui.widget; 3 import hip.api.input.button; 4 import std.internal.digest.sha_SSSE3; 5 import hip.gui.group; 6 7 /** 8 * Screen is where all widgets should be contained. 9 * This way, the event methods are forwarded correctly, there can exist a drag and drop. 10 * Render order by stack is also possible 11 */ 12 class Screen : Group 13 { 14 protected Widget focusedWidget; 15 protected Widget draggedWidget; 16 private Widget widgetHolded; 17 private Widget widgetMouseEntered; 18 19 20 this(){setupEvents();} 21 22 private const(HipButton)* mouseDownEv, mouseUpEv; 23 private const(ScrollListener)* scrollEv; 24 private const(TouchMoveListener)* moveEv; 25 26 27 28 final void setupEvents() 29 { 30 import hip.api.input.core:HipInput, HipInputListener, HipMouseButton; 31 mouseDownEv = HipInputListener.addTouchListener(HipMouseButton.left, 32 (const AHipButtonMetadata meta) 33 { 34 handleMouseDown(); 35 }); 36 37 mouseUpEv = HipInputListener.addTouchListener(HipMouseButton.left, 38 (const(AHipButtonMetadata) meta) 39 { 40 stopDragging(); 41 handleMouseUp(); 42 }, HipButtonType.up); 43 44 moveEv = HipInputListener.addTouchMoveListener((int x, int y) 45 { 46 handleMouseEnter(x, y); 47 startDragging(x, y); 48 }); 49 50 scrollEv = HipInputListener.addScrollListener((float[3] scroll) 51 { 52 handleScroll(scroll); 53 }); 54 } 55 56 57 int findWidget(Widget w) 58 { 59 for(int i = 0; i < children.length; i++) 60 if(children[i] is w) return i; 61 return -1; 62 } 63 64 private void handleMouseDown() 65 { 66 import hip.api; 67 Widget w = findWidgetAt(HipInput.getWorldTouchPosition()); 68 widgetHolded = w; 69 setFocusOn(w); 70 if(w !is null) w.onMouseDown(); 71 } 72 private void handleMouseUp() 73 { 74 import hip.api; 75 if(widgetHolded !is null) 76 { 77 widgetHolded.onMouseUp(); 78 if(findWidgetAt(HipInput.getWorldTouchPosition()) is widgetHolded) 79 widgetHolded.onMouseClick(); 80 } 81 widgetHolded = null; 82 } 83 private void handleScroll(float[3] scroll) 84 { 85 import hip.api; 86 Widget w = findWidgetAt(HipInput.getWorldTouchPosition()); 87 setFocusOn(w); 88 if(w !is null) 89 { 90 import hip.gui.scroll_area; 91 IRawScrollable scrollable = cast(IRawScrollable)w; 92 if(scrollable !is null) scrollable.onRawScroll(scroll); 93 } 94 } 95 96 private void handleMouseEnter(int x, int y) 97 { 98 Widget mEnterWidget = findWidgetAt(x, y); 99 if(widgetMouseEntered !is mEnterWidget) 100 { 101 if(widgetMouseEntered) 102 widgetMouseEntered.onMouseExit(); 103 if(mEnterWidget) 104 mEnterWidget.onMouseEnter(); 105 } 106 widgetMouseEntered = mEnterWidget; 107 } 108 private void startDragging(int x, int y) 109 { 110 if(widgetHolded && !draggedWidget) 111 { 112 setDragging(widgetHolded, x , y); 113 } 114 if(draggedWidget !is null) 115 draggedWidget.onDragged(x, y); 116 } 117 118 private void pushToTop(Widget w) 119 { 120 int pos = findWidget(w); 121 if(pos == children.length-1) return; 122 else if(pos != -1) 123 { 124 import hip.api; 125 import hip.util.algorithm; 126 children[pos+1..$].copyInto(children[pos..$-1]); 127 children[$-1] = w; 128 } 129 } 130 131 void setFocusOn(Widget w) 132 { 133 if(focusedWidget is w) return; 134 if(focusedWidget !is null) 135 focusedWidget.onFocusExit(); 136 focusedWidget = w; 137 if(w !is null) 138 { 139 pushToTop(w); 140 w.onFocusEnter(); 141 } 142 } 143 144 void setDragging(Widget w, int x, int y) 145 { 146 if(w !is null && w.isDraggable) 147 { 148 w.onDragStart(x, y); 149 draggedWidget = w; 150 } 151 } 152 153 void stopDragging() 154 { 155 if(draggedWidget !is null) 156 { 157 draggedWidget.onDragEnd(); 158 draggedWidget = null; 159 } 160 } 161 162 }